#ifndef grille_hpp
#define grille_hpp

#include "projet.hpp"


using namespace std;

class grille{
  humain * h[5][5];
  humain * p[5][5]; 



  void echange(int x,int y, int x1, int y1,char &pcase,char &c1)
  {
    h[x][y]=p[x1][y1];
    h[x1][y1]=p[x][y];

    p[x1][y1]= h[x1][y1];
    p[x][y]= h[x][y];

    char aux=pcase;
    pcase=c1;
    c1=aux;
    
  }
  
  bool test(humain *h, humain *h2,string &noms)const
  { 
    if(noms==h->get_nom()+h2->get_nom()  || noms==h2->get_nom()+h->get_nom())
      return true;
    else return false;


  }

  void cases(int x, int y, char p ,char zone)
  {
    int x1=0; int y1=0;
    int x2=0; int y2=0;
    int x3=0; int y3=0;
    int x4=0; int y4=0;
    char c1='a'; char c2='a'; char c3='a';char c4='a';

    int argent;

   
    if(zone=='b')//zone bords
      {
	if(x==0 && y==0)
	  {
	    x1=0; y1=1;
	    x2=1; y2=0;
	  }

	else if(x==0 && y==4)
	  {
	    x1=0; y1=3;
	    x2=1; y2=4;
	  }

	else if(x==4 && y==0)
	  {
	    x1=3; y1=0;
	    x2=4; y2=1;
	  }

	else if(x==4 && y==4)
	  {
	    x1=3; y1=3;
	    x2=4; y2=3;
	  }

      }//fin zone =='bords'



    if(zone=='c'){//zone cotés

      if(x==0 || x==4)
	{
	  x1=x; y1=y-1;
	  if(x==0)x2=x+1;
	  else x2=x-1;
	  y2=y;
	  x3=x; y3=y+1;
	}
	  
  


      if(y==0 || y==4)
	{
	  x1=x-1; y1=y;
	  x2=x;
	  if(y==0)y2=y+1;
	  else y2=y-1;
	   
	  x3=x+1; y3=y;
	}

      c3=affiche_initiale(h[x3][y3]);

    }//fin de zones cotés


    if(zone=='m')//zone milieu
      {
	x1=x; y1=y-1;
	x2=x-1; y2=y;
	x3=x; y3=y+1;
	x4=x+1; y4=y;

	c3=affiche_initiale(h[x3][y3]);
	c4=affiche_initiale(h[x4][y4]);

      }//fin de zone milieu

    c1=affiche_initiale(h[x1][y1]);
    c2=affiche_initiale(h[x2][y2]);
    
    
    // if(p=='R' || p=='S')//si on opère avec un ronin/samourai
    
    argent=(int)h[x][y]->get_argent();
    if(c1=='C' && (p=='R' || p=='S')){h[x][y]->donner(rand() % argent+1,h[x1][y1]); echange(x,y,x1,y1,p,c1);}
    if(c1=='Y' && (p=='R' || p=='S')){h[x][y]->action(h[x1][y1]);echange(x,y,x1,y1,p,c1);}//si la case est un yakuza

  else  if(c2=='C' && (p=='R' || p=='S')){h[x][y]->donner(rand() % argent+1,h[x2][y2]);echange(x,y,x2,y2,p,c2);}//si la case est un commercant
   else if(c2=='Y' && (p=='R' || p=='S')){h[x][y]->action(h[x2][y2]);echange(x,y,x2,y2,p,c2);}//si la case est un yakuza
    
    //if(zone=='c' || zone=='m')
      // {
else	 if(c3=='C' && (p=='R' || p=='S')){h[x][y]->donner(rand() % argent+1,h[x3][y3]);echange(x,y,x3,y3,p,c3);}//si la case est un commercant
else	 if(c3=='Y' && (p=='R' || p=='S')){h[x][y]->action(h[x3][y3]);echange(x,y,x3,y3,p,c3);}//si la case est un yakuza

	 //	if(zone=='m')
	  // {
else	 if(c4=='C' && (p=='R' || p=='S')){h[x][y]->donner(rand() % argent+1,h[x4][y4]);echange(x,y,x4,y4,p,c4);}//si la case est un commercant
else	 if(c4=='Y' && (p=='R' || p=='S')){h[x][y]->action(h[x4][y4]);echange(x,y,x4,y4,p,c4);}//si la case est un yakuza
	 //}
	//}

    //  else if(p=='Y')//si on opère avec un yakuza
    
    if(c1=='C' && p=='Y'){h[x][y]->action(h[x1][y1]);echange(x,y,x1,y1,p,c1);}//si la case est un commercant
    else if(c2=='C' && p=='Y'){h[x][y]->action(h[x2][y2]);echange(x,y,x2,y2,p,c2);}//si la case est un commercant
   
    //    if(zone=='c' || zone=='m')
    // {
else	 if(c3=='C' && p=='Y'){h[x][y]->action(h[x3][y3]);echange(x,y,x3,y3,p,c3);}//si la case est un commercant
      
	 //	if(zone=='m')
	 // {
else	    if(c4=='C' && p=='Y'){h[x][y]->action(h[x4][y4]);echange(x,y,x4,y4,p,c4);}//si la case est un commercant
	    // }
	    //   }
    
    
  }
  

  void interaction()
  {
    char p;char zone;
    for(int i=0;i<5;i++){
    
      for (int j=0;j<5;j++){

	string echange="";//
	p=affiche_initiale(h[i][j]);
	if(p=='R' || p== 'S' || p=='Y'){
	  if(  (i==0 && (j==0 || j==4))  or  (i==4 && (j==0 || j==4))    ){zone='b';
	    cases(i,j,p,zone);}

	  else if(i==0 || j==0 || i==4 || j==4){zone='c';
	    cases(i,j,p,zone);}

	  else{zone='m';
	    cases(i,j,p,zone);}




	  
	}
      }
    }
  }

  void modifbords()
  {
    int x,y;

    x=0; y=0;//pour la case h[0][0]
    if(h[0][0]!=0){
      for (int essai=0;h[0][0]==p[0][0] && essai<15;essai++){
	x=rand()%2;
	if(x)
	  y=rand()%2;
	else y=1;
      
	if(h[x][y]==0){
	  h[x][y]=p[0][0];
	  h[0][0]=0;
	}

      }
    }
    int w;
    if(h[4][0]!=0){ //pour la case h[4][0]
 
 

      for (int essai=0;h[4][0]==p[4][0] && essai<15;essai++){

	x=4;y=0;
	w=rand()%2 -1;
	x+=w;
 
	if(w)
	  y=rand()%2;
	else y=1;
      
	if(h[x][y]==0){
	  h[x][y]=p[4][0];
	  h[4][0]=0;
	}

      }
    }
    
    
    if(h[4][4]!=0){
      //pour la case h[4][4]
 
 

      for (int essai=0;h[4][4]==p[4][4] && essai<15;essai++){

	x=4;y=4;
	w=rand()%2 -1;
	x+=w;
	if(w)
	  y+=rand()%2-1;
	else y=3;
      
	if(h[x][y]==0){
	  h[x][y]=p[4][4];
	  h[4][4]=0;
	}

      }
    }//fin du if de case



    if(h[0][4]!=0){
      //pour la case h[0][4]
 
 

      for (int essai=0;h[0][4]==p[0][4] && essai<15;essai++){

	x=0;y=4;
	w=rand()%2 ;
	x+=w;
 
	if(w)
	  y+=rand()%2-1;
	else y=3;
      
	if(h[x][y]==0){
	  h[x][y]=p[0][4];

	  h[0][4]=0;
	}

      }
    }//fin du if de case
  }


  void modifhaut(){
    int x,y,w;
    for(int indice=1;indice<4;indice++){

      if(h[0][indice]!=0){ //pour les cases h[0][1-2-3]
 
 

	for (int essai=0;h[0][indice]==p[0][indice] && essai<15;essai++){

	  x=0;y=indice;
	  w=rand()%2 ;
	  x+=w;
 
	  if(w)

	    y+=rand()%3-1;
	  else {
	    while(y==indice)y+=rand()%3-1;}
      
	  if(h[x][y]==0){
	    h[x][y]=p[0][indice];

	    h[0][indice]=0;
	  }
	 
	}
      }//fin du if de case 
    }//fin du for case h[0][1-2-3]

  }


  void modifbas()
  {int x,y,w;

    for(int indice=1;indice<4;indice++){

      if(h[4][indice]!=0){ //pour les cases h[4][1-2-3]
 
 

	for (int essai=0;h[4][indice]==p[4][indice] && essai<15;essai++){
	 
	  x=4;y=indice;
	  w=rand()%2 -1;
	  x+=w;
 
	  if(w)

	    y+=rand()%3-1;
	  else {
	    while(y==indice)y+=rand()%3-1;}
      
	  if(h[x][y]==0){
	    h[x][y]=p[4][indice];

	    h[4][indice]=0;
	  }

	}
      }//fin du if de case
    }//fin du for case h[4][1-2-3]
  }


  void modifgauche()
  {int x,y,w;
 for(int indice=1;indice<4;indice++){

      if(h[indice][0]!=0){ //pour les cases h[1-2-3][0]
 
 

	for (int essai=0;h[indice][0]==p[indice][0] && essai<15;essai++){
	 
	  x=indice;y=0;
	  w=rand()%3 -1;
	  x+=w;
 
	  if(w)

	    y+=rand()%2;
	  else y=1;      
	  if(h[x][y]==0){
	    h[x][y]=p[indice][0];

	    h[indice][0]=0;
	  }
	
	}
      }//fin du if de case
    }//fin du for case h[1-2-3][0]
  }


  void modifdroite()
  {int x,y,w;
 for(int indice=1;indice<4;indice++){

      if(h[indice][4]!=0){ //pour les cases h[1-2-3][4]
 
 

	for (int essai=0;h[indice][4]==p[indice][4] && essai<15;essai++){

	  x=indice;y=4;
	  w=rand()%3 -1;
	  x+=w;
 
	  if(w)

	    y+=rand()%2 -1;
	  else y=3;      
	  if(h[x][y]==0){
	    h[x][y]=p[indice][4];

	    h[indice][4]=0;
	  }
	 
	}
      }//fin du if de case
    }//fin du for case h[1-2-3][4]

  }


  void modifmilieu()
  {int x,y,w;
 for(int indiceX=1;indiceX<4;indiceX++){//pour les cases h[1-2-3][1-2-3]

      for(int indice=1;indice<4;indice++){

	if(h[indiceX][indice]!=0){ 
 
 

	  for (int essai=0;h[indiceX][indice]==p[indiceX][indice] && essai<15;essai++){

	    x=indiceX;y=indice;
	    w=rand()%3-1 ;
	    x+=w;
 
	    if(w)

	      y+=rand()%3-1;
	    else {
	      while(y==indice)y+=rand()%3-1;}
      
	    if(h[x][y]==0){
	      h[x][y]=p[indiceX][indice];

	      h[indiceX][indice]=0;
	    }
	 
	  }
	}//fin du if de case 
      }//fin du for case h
    }//fin du for case h[1-2-3][1-2-3]
  }


  char affiche_initiale(humain *h)const
  {
   
    if(h!=0){
  
      if(typeid(*h)==typeid(commercant))
	return 'C';
      if(typeid(*h)==typeid(ronin))
	return 'R';
      if(typeid(*h)==typeid(yakuza))
	return 'Y';
      if(typeid(*h)==typeid(samourai))
	return 'S';
     
    }
    return '.';
  }



  string center(string e)const
  {

    ostringstream s;
    int l=e.size();
    int pos=(int)((23-l)/2);;
    for(int i=0;i<pos-1;i++)

      s<<" ";
    s<<e;
    return s.str();
  }

  void affiche_argent(humain*h) const
  {
    cout.fill(' ');cout.width(23);
    if(h!=0)
      cout<<h->get_argent();
    
    else cout<<"" ;
    
  }


 
  string affiche_humain(humain*h) const
  {
    if(h!=0){
     

      ostringstream oss; 
      oss<<"("<<h->get_nom()<<")";
    
      return center(oss.str());
     
    }
    else return "";
 
  }


public: 
  ~grille(){
    for (int i=0;i<5;i++){
      for (int j=0;j<5;j++){
	        

	if(h[i][j]) delete h[i][j];
	h[i][j]=0;

      }
    }

 
  }
 void bonjour() const{
    for(int i=0;i<5;i++){
    
      for (int j=0;j<5;j++){
	if(h[i][j]!=0)
	  h[i][j]->dire_bonjour();
      }
    }
  }

  grille()
  {
    for(int i=0;i<5;i++){///initialisation des pointeurs à 0
    
      for (int j=0;j<5;j++){
	h[i][j]=0;

      }

    }



    int nbr=0;
    int nbc=0;
    int nby=0;
    int nbs=0;
  
   

    int x;
    int y;
    while(nbr<2){
      srand ( time(NULL));

      x= rand() %5;
      y= rand() %5;

      if(nbr==0){
	if(h[x][y]==0){//si la case est vide on cree un ronin et on incrémente 
	  h[x][y]= new ronin("roro", 61, "jus de pomme");nbr++;}
      }
     
             

      if(h[x][y]==0 ){//si la case est vide et est différente on cree un humain et on incrémente 
	h[x][y]= new ronin("chevalier", 120, "jus de raisin");nbr++;}
    }

   



    while(nby<2){
    
      x= rand() %5;
      y= rand() %5;
      if(nby==0){
	if(h[x][y]==0){//si la case est vide on cree un humain et on incrémente 
	  h[x][y]= new yakuza("yaku le noir", 42, "jus d'orange", "war");nby++;}
      }

      if(h[x][y]==0 ){//si la case est vide et est différente on cree un humain et on incrémente 
	h[x][y]= new yakuza("yaku le blanc", 12, "jus de pamplemousse", "furies");nby++;}
    }


    while(nbc<2){
    
      x= rand() %5;
      y= rand() %5;
      if(nbc==0){
	if(h[x][y]==0){//si la case est vide on cree un humain et on incrémente 
	  h[x][y]= new commercant("marchand", 35); nbc++;}
      }

      if(h[x][y]==0 ){//si la case est vide et est différente on cree un humain et on incrémente 
	h[x][y]= new commercant("forgeron", 5); nbc++;}
    }


 

    while(nbs<2){
     
      x= rand() %5;
      y= rand() %5;
      if(nbs==0){
	if(h[x][y]==0){//si la case est vide on cree un humain et on incrémente 
	  h[x][y]= new samourai("sami", 102, "pepsi", "JCVD"); nbs++;}
      }

      if(h[x][y]==0 ){//si la case est vide et est différente on cree un humain et on incrémente 
	h[x][y]= new samourai("mourai", 1002, "coca", "Louis XIV") ; nbs++;}
    }

    for(int i=0;i<5;i++){
    
      for (int j=0;j<5;j++){

	p[i][j]=h[i][j];
      }
    }

    //	 cout<<"nbs="<<nbs<<" nbc="<<nbc<<" nbr="<<nbr<<" nby="<<nby<<endl; 
    affiche();
 bonjour();
  }

  //////////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////////

 


  void affiche()const
  {
    // system("clear") ;
    int x=0;
    int y=0;

   
    for(int i=0;i<5;i++)//BOUCLE PRINCIPALE pour répeter 5 fois une ligne
      {
	cout<<"x-----------------------------------------------------------------------------------------------------------------------x"<<endl;
	cout<<"|";


	for(int k=0;k<4;k++)//boucle pour afficher les Initiales
	  {
	    cout.fill(' ');cout.width(23);
	    cout<<left<<affiche_initiale(h[x][y++]);cout<<"|";
	  
	  }
	

	cout.fill(' ');cout.width(23);
	cout<<affiche_initiale(h[x][y]);cout<<"|"<<endl;
	y=0;
      
      
	cout<<"|";
      

	for(int l=0;l<4;l++)//boucle pour afficher les noms
	  {
	    cout.fill(' ');cout.width(23);
	    cout<<affiche_humain(h[x][y++]);cout<<"|";
	  }


	cout.fill(' ');cout.width(23);


	cout<<affiche_humain(h[x][y]);cout<<"|"<<endl;
	y=0;
      
	cout<<"|";
	for(int m=0;m<4;m++)//boucle pour afficher l'argent
	  {
	 
	    affiche_argent(h[x][y++]); cout<<"|";
	
	  }

	affiche_argent(h[x++][y]);cout<<"|"<<endl;
	y=0;
    
   
      }


    cout<<"x-----------------------------------------------------------------------------------------------------------------------x"<<endl;


   
    /*cout<<"voulez vous reafficher?"<<endl;
      char c;
      cin>>c;
      if(c=='o')return affiche();*/
  }




 


     void modif()
  {
   
    for(int a=0;a<3;a++){

      modifbords();

      modifhaut();

      modifbas();

      modifgauche();

      modifdroite();

      modifmilieu();

   
    for(int i=0;i<5;i++){
    
      for (int j=0;j<5;j++){

	p[i][j]=h[i][j];
      }
    }

    cout<<"Déplacements effectués"<<endl;
    affiche();
    interaction();
    cout<<endl;
    cout<<"grille après interactions effectuées:"<<endl;
    affiche();

  }
  }//fin de la fonction modif  

};

#endif
